﻿
namespace HSS.Xaml.UI.Interactivity
{
	#region Using Directives
	using System;
	using System.Reflection;
	using System.Windows;
	using System.Windows.Input;
	using System.Windows.Interactivity;
	#endregion

	#region DoubleClickCommandAction
	/// <summary>
	/// Executes a specified ICommand when invoked by a <see cref="DoubleClickTrigger{T}"/>.
	/// </summary>
	public sealed class DoubleClickCommandAction : TriggerAction<DependencyObject>, IDoubleClickAction
	{
		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		public DoubleClickCommandAction()
		{
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the name of the command this action should invoke.
		/// </summary>
		/// <value>The name of the command this action should invoke.</value>
		/// <remarks>This property will be superseded by the Command property if both are set.</remarks>
		public string CommandName
		{
			get { return this.commandName; }
			set
			{
				if (this.CommandName != value)
					this.commandName = value;
			}
		} string commandName;
		/// <summary>
		/// Gets or sets the command this action should invoke. This is a dependency property.
		/// </summary>
		/// <value>The command to execute.</value>
		/// <remarks>This property will take precedence over the CommandName property if both are set.</remarks>
		public ICommand Command
		{
			get
			{
				return (ICommand)base.GetValue(CommandProperty);
			}
			set
			{
				base.SetValue(CommandProperty, value);
			}
		}
		/// <summary>
		/// Gets or sets a DependencyProperty for the Command Property.
		/// </summary>
		public static readonly DependencyProperty CommandProperty =
			DependencyProperty.Register(
			"Command",
			typeof(ICommand),
			typeof(DoubleClickCommandAction),
			null);
		/// <summary>
		/// Gets or sets the command parameter. This is a dependency property.
		/// </summary>
		/// <value>The command parameter.</value>
		/// <remarks>This is the value passed to ICommand.CanExecute and ICommand.Execute.</remarks>
		public object CommandParameter
		{
			get
			{
				return base.GetValue(CommandParameterProperty);
			}
			set
			{
				base.SetValue(CommandParameterProperty, value);
			}
		}
		/// <summary>
		/// Gets or sets a DependencyProperty for the CommandParameter Property.
		/// </summary>
		public static readonly DependencyProperty CommandParameterProperty =
			DependencyProperty.Register(
			"CommandParameter",
			typeof(object),
			typeof(DoubleClickCommandAction),
			null);
		#endregion

		#region Methods
		/// <summary>
		/// Invokes the action.
		/// </summary>
		/// <param name="parameter">Does not require a parameter and may be set to a null reference.</param>
		protected override void Invoke(object parameter)
		{
			if (base.AssociatedObject != null)
			{
				var command = this.ResolveCommand();
				if ((command != null) && command.CanExecute(this.CommandParameter))
					command.Execute(this.CommandParameter);
			}
		}
		void IDoubleClickAction.DoubleClickInvoke()
		{
			this.Invoke(null);
		}
		private ICommand ResolveCommand()
		{
			ICommand command = null;
			if (this.Command != null)
			{
				return this.Command;
			}
			if (base.AssociatedObject != null)
			{
				foreach (var info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
				{
					if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal))
					{
						command = (ICommand)info.GetValue(base.AssociatedObject, null);
						if (null != command)
							return command;
					}
				}
			}
			return command;
		}
		#endregion
	}
	#endregion
}